package com.whereta.service.impl;

import com.whereta.dao.IMenuDao;
import com.whereta.dao.IMenuPermissionDao;
import com.whereta.dao.IPermissionDao;
import com.whereta.model.Menu;
import com.whereta.model.MenuPermission;
import com.whereta.model.Permission;
import com.whereta.service.IMenuService;
import com.whereta.vo.MenuCreateVO;
import com.whereta.vo.MenuEditVO;
import com.whereta.vo.ResultVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by vincent on 15-8-27.
 */
@Service("menuService")
public class MenuServiceImpl implements IMenuService {
    @Resource
    private IMenuDao menuDao;
    @Resource
    private IMenuPermissionDao menuPermissionDao;
    @Resource
    private IPermissionDao permissionDao;

    /**
     * 获取显示菜单
     *
     * @return
     */
    public List<Map<String, Object>> selectShowMenus(Integer rootId) {

        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        //授权的菜单集合
        List<Menu> menuPermittedList = new ArrayList<Menu>();
        //获取所有菜单
        List<Menu> menuList = menuDao.selectAll();
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();

        Subject subject = SecurityUtils.getSubject();
        for (Menu menu : menuList) {
            Set<Integer> permissionIdSet = menuPermissionDao.selectPermissionIdSet(menu.getId());
            //权限key集合
            List<String> perKeyList = new ArrayList<String>();
            if (permissionIdSet != null && !permissionIdSet.isEmpty()) {
                for (Integer perId : permissionIdSet) {
                    Permission permission = permissionDao.get(permissionList, perId.intValue());
                    perKeyList.add(permission.getKey());
                }
            }
            //判断权限
            String[] permissions = perKeyList.toArray(new String[]{});
            boolean permittedAll = subject.isPermittedAll(permissions);
            if (permittedAll) {
                menuPermittedList.add(menu);
            }
        }
        List<Integer> childrenIdList = null;
        if (rootId != null) {
            childrenIdList = getChildrenMenuIds(menuList, rootId);
            childrenIdList.add(rootId);
        }

        List<Menu> rootMenus = getRootMenus(menuPermittedList);
        for (Menu menu : rootMenus) {
            if (childrenIdList == null || !childrenIdList.contains(menu.getId())) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id", menu.getId());
                map.put("text", menu.getName());
                map.put("order", menu.getOrder());
                //菜单额外属性
                Map<String, Object> attrMap = new HashMap<String, Object>();
                attrMap.put("url", menu.getUrl());
                map.put("attributes", attrMap);
                map.put("url", menu.getUrl());
                List<Map<String, Object>> childrenMenus = getChildrenMenus(menuPermittedList, menu.getId(), childrenIdList);
                map.put("children", childrenMenus);
                maps.add(map);
            }
        }
        return maps;
    }

    /**
     * 创建菜单
     *
     * @param createVO
     * @return
     */
    public ResultVO createMenu(MenuCreateVO createVO) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有菜单
        List<Menu> menuList = menuDao.selectAll();
        //父级菜单
        if (createVO.getParentId() != null) {
            Menu parentMenu = menuDao.get(menuList, createVO.getParentId());
            if (parentMenu == null) {
                resultVO.setOk(false);
                resultVO.setMsg("父级菜单不存在");
                return resultVO;
            }
        }
        //菜单名字不能重复
        for(Menu menu:menuList){
            if(menu.getName().equals(createVO.getName())){
                resultVO.setOk(false);
                resultVO.setMsg("菜单名字已存在");
                return resultVO;
            }
        }

        //添加菜单
        Menu menu = new Menu();
        menu.setOrder(createVO.getOrder());
        menu.setName(createVO.getName());
        menu.setParentId(createVO.getParentId());
        menu.setUrl(createVO.getUrl());
        menuDao.createMenu(menu);
        resultVO.setMsg("创建菜单成功");
        return resultVO;
    }

    /**
     * 删除菜单
     *
     * @param menuId
     * @return
     */
    public ResultVO deleteMenu(int menuId) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有菜单
        List<Menu> menus = menuDao.selectAll();
        //获取菜单
        Menu menu = menuDao.get(menus, menuId);
        if (menu == null) {
            resultVO.setOk(false);
            resultVO.setMsg("菜单不存在");
            return resultVO;
        }
        //获取子级菜单
        List<Integer> childrenMenuIds = getChildrenMenuIds(menus, menuId);
        //删除菜单
        menuDao.deleteMenu(menuId);
        menuPermissionDao.deleteByMenuId(menuId);
        for (Integer id : childrenMenuIds) {
            menuDao.deleteMenu(id);
            menuPermissionDao.deleteByMenuId(id);
        }
        resultVO.setMsg("删除菜单成功");
        return resultVO;
    }

    /**
     * 编辑菜单
     *
     * @param editVO
     * @return
     */
    public ResultVO editMenu(MenuEditVO editVO) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有菜单
        List<Menu> menus = menuDao.selectAll();
        //获取菜单
        Menu menu = menuDao.get(menus, editVO.getId());
        if (menu == null) {
            resultVO.setOk(false);
            resultVO.setMsg("菜单不存在");
            return resultVO;
        }
        //父级菜单
        if (editVO.getParentId() != null) {
            Menu parentMenu = menuDao.get(menus, editVO.getParentId());
            if (parentMenu == null) {
                resultVO.setOk(false);
                resultVO.setMsg("父级菜单不存在");
                return resultVO;
            }
            List<Integer> childrenMenuIds = getChildrenMenuIds(menus, editVO.getId());
            childrenMenuIds.add(editVO.getId());
            if (childrenMenuIds.contains(editVO.getParentId())) {
                resultVO.setOk(false);
                resultVO.setMsg("所在菜单的上级不能为自己所在菜单或者下级菜单");
                return resultVO;
            }
        }
        //菜单名字不能重复
        for(Menu m:menus){
            if(m.getName().equals(editVO.getName())&&menu.getId()!=editVO.getId()){
                resultVO.setOk(false);
                resultVO.setMsg("菜单名字已存在");
                return resultVO;
            }
        }
        //更新菜单
        Menu update = new Menu();
        update.setUrl(editVO.getUrl());
        update.setParentId(editVO.getParentId());
        update.setName(editVO.getName());
        update.setOrder(editVO.getOrder());
        update.setId(editVO.getId());
        menuDao.updateMenu(update);
        resultVO.setMsg("编辑菜单成功");
        return resultVO;
    }

    /**
     * 菜单授权
     *
     * @param menuId
     * @param perIdArray
     * @return
     */
    public ResultVO grantPermissions(int menuId, Integer[] perIdArray) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有菜单
        List<Menu> menus = menuDao.selectAll();
        //获取菜单
        Menu menu = menuDao.get(menus, menuId);
        if (menu == null) {
            resultVO.setOk(false);
            resultVO.setMsg("菜单不存在");
            return resultVO;
        }

        //获取所有权限
        List<Permission> permissions = permissionDao.selectAll();

        Set<Integer> perIdSet = new HashSet<Integer>();

        for (Integer id : perIdArray) {
            perIdSet.add(id);
        /*    List<Integer> childrenPermissionIds = PermissionServiceImpl.getChildrenPermissionIds(id, permissions);
            perIdSet.addAll(childrenPermissionIds);*/
        }

        //删除菜单权限
        menuPermissionDao.deleteByMenuId(menuId);
        //授权
        if (!perIdSet.isEmpty()) {
            for (Integer perId : perIdSet) {
                MenuPermission menuPermission = new MenuPermission();
                menuPermission.setMenuId(menuId);
                menuPermission.setPermissionId(perId);
                menuPermissionDao.addMenuPermission(menuPermission);

            }
        }
        resultVO.setMsg("授权成功");
        return resultVO;
    }

    /**
     * 获取子级菜单
     *
     * @param menus
     * @param parentId
     * @return
     */
    private List<Map<String, Object>> getChildrenMenus(List<Menu> menus, Integer parentId, List<Integer> excludeChildrenIdList) {
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        for (Menu menu : menus) {
            if ((parentId == null && menu.getParentId() == null) || (parentId != null && menu.getParentId() != null && menu.getParentId().intValue() == parentId.intValue())) {
                if (excludeChildrenIdList == null || !excludeChildrenIdList.contains(menu.getId())) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("id", menu.getId());
                    map.put("text", menu.getName());
                    //菜单额外属性
                    Map<String, Object> attrMap = new HashMap<String, Object>();
                    attrMap.put("url", menu.getUrl());
                    map.put("attributes", attrMap);
                    map.put("url", menu.getUrl());
                    map.put("order", menu.getOrder());
                    List<Map<String, Object>> childrenMenus = getChildrenMenus(menus, menu.getId(), excludeChildrenIdList);
                    map.put("children", childrenMenus);
                    mapList.add(map);
                }
            }
        }
        return mapList;
    }

    /**
     * 获取根菜单
     *
     * @param menus
     * @return
     */
    private List<Menu> getRootMenus(List<Menu> menus) {
        List<Menu> rootMenus = new ArrayList<Menu>();
        for (Menu menu : menus) {
            if (menu.getParentId() == null) {
                rootMenus.add(menu);
                continue;
            }
            Menu parentMenu = menuDao.get(menus, menu.getParentId().intValue());
            if (parentMenu == null) {
                rootMenus.add(menu);
            }
        }
        return rootMenus;
    }

    /**
     * 获取所有子级菜单id集合
     *
     * @param menuList
     * @param parentId
     * @return
     */
    private List<Integer> getChildrenMenuIds(List<Menu> menuList, Integer parentId) {
        List<Integer> list = new ArrayList<Integer>();
        for (Menu menu : menuList) {
            if ((parentId == null && menu.getParentId() == null) || (parentId != null && menu.getParentId() != null && parentId.intValue() == menu.getParentId().intValue())) {
                list.add(menu.getId().intValue());
                list.addAll(getChildrenMenuIds(menuList, menu.getId().intValue()));
            }
        }
        return list;
    }
}
